package com.example.demo.component.helper;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @ClassName http_client_helper
 * @Description 网络客户端帮手类，包括Post和Get等功能
 * @date 2022/11/7 9:35
 * @Author Junhao Qu
 * @Version 1.0
 */
public class http_client_helper {


    /**
     * 设置参数头部的格式
     *
     * @param request  请求
     * @param response 回复
     */
    public static void set_header(HttpServletRequest request, HttpServletResponse response) {
        try {
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "POST");
            response.setHeader("Access-Control-Allow-Headers", "x-requested-with,content-type");
            response.setContentType("text/html;charset=UTF-8");
            request.setCharacterEncoding("UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取请求中的参数，支持Json和Form-data两种格式
     *
     * @param request 请求
     * @return 字典形式的参数
     */
    public static Map<String, String> get_param_in_request(HttpServletRequest request) {
        Map<String, String> param = new HashMap<>();
        try {
            Enumeration<String> param_in_request = request.getParameterNames();
            while (param_in_request.hasMoreElements()) {
                String key = param_in_request.nextElement();
                String val = request.getParameter(key);
                param.put(key, val);
            }
            if (param.size() == 0) {
                ServletInputStream input_stream = request.getInputStream();
                InputStreamReader reader = new InputStreamReader(input_stream, StandardCharsets.UTF_8);
                BufferedReader br = new BufferedReader(reader);
                StringBuilder sb = new StringBuilder();
                String read_line = "";
                while ((read_line = br.readLine()) != null) {
                    sb.append(read_line).append("\n");
                }
                br.close();
                String str = sb.toString().replace("\\", "/");
                if (!str.equals("")) {
                    JSONObject param_obj = JSONObject.parseObject(str);
                    for (String key : param_obj.getInnerMap().keySet()) {
                        param.put(key, param_obj.get(key).toString());
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();

        }
        return param;
    }

    /**
     * 标准POST方法
     *
     * @param url 目的地址
     * @param map 参数
     * @return 完成POST以后的结果
     */
    public static String post(String url, Map<String, String> map) {
        String result = null;
        try (CloseableHttpClient http_client = HttpClients.createDefault()) {
            List<NameValuePair> form_params = new ArrayList<>();
            for (Map.Entry<String, String> entry : map.entrySet()) {
                form_params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(form_params, Consts.UTF_8);
            HttpPost http_post = new HttpPost(url);
            http_post.setEntity(entity);
            result = "";
            CloseableHttpResponse response = http_client.execute(http_post);
            HttpEntity entity1 = response.getEntity();
            result = EntityUtils.toString(entity1);
        } catch (IOException e) {
            e.printStackTrace();

        }
        return result;
    }

    /**
     * 发送get请求
     *
     * @param url   请求URL
     * @param param 请求参数 key:value url携带参数 或者无参可不填
     * @return 请求结果
     */
    public static String doGet(String url, Map<String, String> param) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String resultString = "";
        CloseableHttpResponse response = null;
        try {
            URIBuilder builder = new URIBuilder(url);
            if (param != null) {
                for (String key : param.keySet()) {
                    builder.addParameter(key, param.get(key));
                }
            }
            URI uri = builder.build();
            HttpGet httpGet = new HttpGet(uri);
            response = httpClient.execute(httpGet);
            if (response.getStatusLine().getStatusCode() == 200) {
                resultString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return resultString;
    }


    /**
     * 带用户名和密码验证的POST方法
     *
     * @param url      目的地址
     * @param map      参数
     * @param username 用户名
     * @param token    token或密码
     * @return 完成POST以后的结果
     */
    public static String post_with_authentication(String url, Map<String, String> map, String username, String token) {
        String result = null;
        try (CloseableHttpClient http_client = HttpClients.createDefault()) {
            List<NameValuePair> form_params = new ArrayList<>();
            for (Map.Entry<String, String> entry : map.entrySet()) {
                form_params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(form_params, Consts.UTF_8);
            HttpPost http_post = new HttpPost(url);
            http_post.addHeader("Authorization", get_header(username, token));
            http_post.setEntity(entity);
            result = "";
            CloseableHttpResponse response = http_client.execute(http_post);
            HttpEntity entity1 = response.getEntity();
            result = EntityUtils.toString(entity1);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 带用户名和密码验证的GET方法
     *
     * @param url      目的地址
     * @param data     参数
     * @param username 用户名
     * @param token    token或密码
     * @return 完成GET以后的结果
     */
    public static String get_with_authentication(String url, Map<String, String> data, String username, String token) {
        String response_content = null;
        try {
            CredentialsProvider provider = new BasicCredentialsProvider();
            UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, token);
            provider.setCredentials(AuthScope.ANY, credentials);
            CloseableHttpClient client = HttpClientBuilder.create().setDefaultCredentialsProvider(provider).build();
            url = url + "?" + get_get_param_by_map(data);
            HttpGet http_get = new HttpGet(url);
            http_get.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
            CloseableHttpResponse response = (CloseableHttpResponse) client.execute(http_get);
            HttpEntity entity = response.getEntity();
            response_content = EntityUtils.toString(entity, "UTF-8");
            response.close();
            client.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return response_content;
    }

    /**
     * 帮手方法，获取验证部分的头部
     *
     * @param username 用户名
     * @param token    token或密码
     * @return 验证头部
     */
    private static String get_header(String username, String token) {
        String auth = username + ":" + token;
        byte[] encoded_auth = Base64.getEncoder().encode(auth.getBytes(StandardCharsets.US_ASCII));
        return "Basic " + new String(encoded_auth);
    }

    /**
     * 帮手方法，拼接GET请求中的参数
     *
     * @param data 参数
     * @return URL
     */
    private static String get_get_param_by_map(Map<String, String> data) {
        StringBuilder sb = new StringBuilder();
        for (String key : data.keySet()) {
            sb.append(key);
            sb.append("=");
            sb.append(data.get(key));
            sb.append("&");
        }
        String str = sb.toString();
        return str.substring(0, str.length() - 1);
    }

}
